=begin pod :tag<tutorial>

=TITLE Testing

=SUBTITLE Writing and running tests in Perl 6


Testing code is an integral part of software development.
Tests provide automated, repeatable
verifications of code behaviour, and ensures your code works as expected.

In Perl 6, the L<Test|https://github.com/rakudo/rakudo/blob/master/lib/Test.pm6>
module provides a testing framework. Perl 6's official spectest suite uses C<Test>.

The testing functions emit output conforming to the L<Test Anything
Protocol|http://testanything.org>.

=head1 Reference

=item L«C<plan>|/language/testing#index-entry-plan-plan($count)»
    — declare how many tests you expect to run

=item L«C<done-testing>|/language/testing#index-entry-done-testing»
    — indicate the test suite has finished (used instead of C<plan>)

=item L«C<bail-out>|/language/testing#index-entry-bail-out-bail-out($reason?)»
    — abort the test suite by exiting (considered a failure)

=item L«C<todo>|/language/testing#index-entry-todo-todo($reason,_$count_=_1)»
    — mark a given number of tests as TODO

=item L«C<skip>|/language/testing#index-entry-skip-skip($reason,_$count_=_1)»
    — mark a given number of tests as SKIP

=item L«C<skip-rest>|/language/testing#index-entry-skip-rest-skip-rest($reason?)»
    — mark all of the remaining tests as SKIP


=item L«C<diag>|/language/testing#index-entry-diag-diag($message)»
    — display a diagnostic message

=item L«C<subtest>|/language/testing#index-entry-subtest-subtest(&subtests,_$description?)»
    — declare a subtest


=item L«C<pass>|/language/testing#index-entry-pass-flunk-pass($description?),_flunk($description?)»
    — proclaim one test as passed

=item L«C<flunk>|/language/testing#index-entry-pass-flunk-pass($description?),_flunk($description?)»
    — proclaim one test as failed


=item L«C<ok>|/language/testing#index-entry-ok_nok-ok($value,_$description?),_nok($condition,_$description?)»
    — is truthy

=item L«C<nok>|/language/testing#index-entry-ok_nok-ok($value,_$description?),_nok($condition,_$description?)»
    — is falsy


=item L«C<cmp-ok>|/language/testing#index-entry-cmp-ok-cmp-ok($value,_$comparison,_$expected,_$description?)»
    — compare with a value using the given operator

=item L«C<is>|/language/testing#index-entry-is_testing»
    — is a given value (C<cmp> semantics)

=item L«C<is-deeply>|/language/testing#index-entry-is-deeply-is-deeply($value,_$expected,_$description?)»
    — is a given value (C<eqv> semantics)

=item L«C<isnt>|/language/testing#index-entry-isnt-isnt($value,_$expected,_$description?)»
    — is I<not> a given value (C<cmp> semantics)

=item L«C<is-approx>|/language/testing#index-entry-is-approx-is-approx($value,_$expected,_$description?)»
    — approximately equals to a numerical value


=item L«C<like>|/language/testing#index-entry-like-like($value,_$expected-regex,_$description?)»
    — matches a given regex

=item L«C<unlike>|/language/testing#index-entry-unlike-unlike($value,_$expected-regex,_$description?)»
    — does not match a given regex


=item L«C<use-ok>|/language/testing#index-entry-use-ok-use-ok($module)»
    — a module can be C<use>d

=item L«C<isa-ok>|/language/testing#index-entry-isa-ok-isa-ok($value,_$expected-type,_$description?)»
    — an object C<.isa> given type

=item L«C<does-ok>|/language/testing#index-entry-does-ok-does-ok($variable,_$role,_$description?)»
    — an object C<does> a given role

=item L«C<can-ok>|/language/testing#index-entry-can-ok-can-ok($variable,_$method-name,_$description?)»
    — an object C<.^can> a method


=item L«C<dies-ok>|/language/testing#index-entry-dies-ok-dies-ok($code,_$description?)»
    — a given block of code dies

=item L«C<lives-ok>|/language/testing#index-entry-lives-ok-lives-ok($code,_$description?)»
    — a given block of code does not die

=item L«C<eval-dies-ok>|/language/testing#index-entry-eval-dies-ok-eval-dies-ok($string,_$description?)»
    — a given string of code dies when evaled

=item L«C<eval-lives-ok>|/language/testing#index-entry-eval-lives-ok-eval-lives-ok($string,_$description?)»
    — a given string of code does not die when evaled

=item L«C<throws-like>|/language/testing#index-entry-throws-like»
    — a given block of code (or string to be evaled) throws a given exception

=head1 Writing tests

As with any Perl project, the tests live under the C<t> directory in the
project's base directory.

A typical test file looks something like this:

=begin code :skip-test
use v6.c;
use Test;      # a Standard module included with Rakudo
use lib 'lib';

plan $num-tests;

# .... tests

done-testing;  # optional with 'plan'
=end code

We ensure that we're using Perl 6, via the C<use v6.c> pragma, then we load
the C<Test> module and specify where our libraries are.  We then specify how
many tests we I<plan> to run (such that the testing framework can tell us if
more or fewer tests were run than we expected) and when finished with the
tests, we use I<done-testing> to tell the framework we are done.

=head2 Thread Safety

Note that routines in C<Test> module are I<not> thread-safe. This means you
should not attempt to use the testing routines in multiple threads simultaneously,
as the L<TAP|https://testanything.org/> output might
come out of order and confuse the program interpreting it.

There are no current plans to make it thread safe. If threaded-testing is
crucial to you, you may find some suitable
L<ecosystem modules|https://modules.perl6.org/search/?q=Test> to use
instead of C<Test> for your testing needs.

=head1 Running tests

Tests can be run individually by specifying the test filename on the
command line:

=for code :lang<shell>
$ perl6 t/test-filename.t

Or via the L<prove|http://perldoc.perl.org/prove.html> command from Perl 5,
where C<perl6> is specified as the executable that runs the tests:

=for code :lang<shell>
$ prove --exec perl6 -r t

To abort the test suite upon first failure, set the
C<PERL6_TEST_DIE_ON_FAIL> environmental variable:

=for code :lang<shell>
$ PERL6_TEST_DIE_ON_FAIL=1 perl6 t/test-filename.t

The same variable can be used within the test file. Set it before loading
the C<Test> module:

    BEGIN %*ENV<PERL6_TEST_DIE_ON_FAIL> = 1;
    use Test;
    ...

=head1 Test plans

=item X<plan($count)|plan>

Specify the count of tests -- usually written at the beginning of a
test file.

    plan 15;   # expect to run 15 tests

In C<subtest>s, C<plan> is used to specify the count of tests within
the subtest.

If a C<plan> is used, it's not necessary to specify the end of testing with
C<done-testing>.

You can also provide a C<:skip-all> named argument instead of a test count,
to indicate that you want to skip all of the tests. Such a plan will
call L«C<exit>|/routine/exit», unless used inside of a C<subtest>.

    plan :skip-all<These tests are only for Windows> unless $*DISTRO.is-win;
    plan 1;
    ok dir 'C:/'; # this won't get run on non-Windows

If used in a C<subtest>, it will instead C<return> from that
C<subtest>'s L«C<Callable>|/type/Callable». For that reason, to be able to
use C<:skip-all> inside a C<subtest>, you must use a C<sub> instead of a
regular block:

    plan 2;
    subtest "Some Windows tests" => sub { # <-- note the `sub`; can't use bare block
        plan :skip-all<We aren't on Windows> unless $*DISTRO.is-win;
        plan 1;
        ok dir 'C:/'; # this won't get run on non-Windows
    }
    ok 42; # this will run everywhere and isn't affected by skip-all inside subtest

Note that C<plan> with C<:skip-all> is to avoid performing any tests without marking the
test run as failed (i.e. the plan is to not run anything and that's all good). Use
L«C<skip-rest>|/language/testing#index-entry-skip-rest-skip-rest($reason?)» to skip
all further tests, once the run has started (i.e. planned to run some tests, maybe
even ran some, but now we're skipping all the rest of them). Use
L«C<bail-out>|/language/testing#index-entry-bail-out-bail-out($reason?)» to fail the
test run without running any further tests (i.e. things are so bad, there's no point
in running anything else; we've failed).

=item X<done-testing>

Specify that testing has finished.  Use this function when you don't
have a C<plan> with the number of tests to run. A C<plan> is not
required when using C<done-testing>.

It's recommended that the C<done-testing> function be removed and replaced
with a C<plan> function when all tests are finalized. Use of C<plan> can help
detect test failures otherwise not reported because tests were accidentally skipped
due to bugs in the tests or bugs in the compiler. For example:

    sub do-stuff {@};
    use Test;
    ok .is-prime for do-stuff;
    done-testing;

    # output:
    1..0

The above example is where a C<done-testing> fails. C<do-stuff()> returned
nothing and tested nothing, even though it should've returned results to test. But
the test suite doesn't know how many tests were meant to be run, so it passes.

Adding C<plan> gives a true picture of the test:

    sub do-stuff {@};
    use Test;
    plan 1;
    ok .is-prime for do-stuff;

    # output:
    1..1
    # Looks like you planned 1 test, but ran 0

Note that leaving the C<done-testing> in place will have no effect on the new test
results, but it should be removed for clarity.

=head1 Testing return values

The C<Test> module exports various functions that check the return value of a
given expression and produce standardized test output.

In practice, the expression will often be a call to a function or method that
you want to unit-test.

=head2 By C<Bool> value

=item X<ok($value, $description?), nok($condition, $description?)|ok,nok>

The C<ok> function marks a test as passed if the given C<$value>
evaluates to C<True>. The C<nok> function marks
a test as passed if the given value evaluates to C<False>. Both functions
accept an optional C<$description> of the test.

    my $response; my $query; ...;
    ok  $response.success, 'HTTP response was successful';
    nok $query.error,      'Query completed without error';

In principle, you could use C<ok> for every kind of comparison test, by
including the comparison in the expression passed to C<$value>:

    sub factorial($x) { ... };
    ok factorial(6) == 720, 'Factorial - small integer';

However, where possible it's better to use one of the specialized comparison
test functions below, because they can print more helpful diagnostics output in
case the comparison fails.

=head2 By string comparison

X<|is,testing>
=item is($value, $expected, $description?)

Marks a test as passed if C<$value> and C<$expected> compare positively with
the L<eq operator|/routine/eq>, unless C<$expected> is a type object, in which
case C<===> operator will be used instead; accepts an optional C<$description> of the test.

B<NOTE:> C<eq> operator the C<is()> uses stringifies,
which means C<is()> is not a good function for testing more complex things, such
as lists: C<is (1, (2, (3,))), [1, 2, 3]> passes the test, even though the operands
are vastly different. For those cases, use
L«C<is-deeply> routine|/language/testing#index-entry-is-deeply-is-deeply($value,_$expected,_$description?)»

    my $pdf-document; sub factorial($x) { ... }; ...;
    is $pdf-document.author, "Joe", 'Retrieving the author field';
    is factorial(6),         720,   'Factorial - small integer';
    my Int $a;
    is $a, Int, 'The variable $a is an unassigned Int';

B<Note:> if I<only> whitespace differs between the values, C<is()> will output failure
message differently, to show the whitespace in each values. For example, in the
output below, the second test shows the literal C<\t> in the C<got:> line:

    is "foo\tbar", "foo\tbaz";   # expected: 'foo     baz'␤#      got: 'foo   bar'
    is "foo\tbar", "foo    bar"; # expected: "foo    bar"␤#      got: "foo\tbar"

=item X<isnt($value, $expected, $description?)|isnt>

Marks a test as passed if C<$value> and C<$expected> are B<not> equal using
the same rules as C<is()>.  The function accepts an optional C<$description>
of the test.

    isnt pi, 3, 'The constant π is not equal to 3';

    my Int $a = 23;
    $a = Nil;
    isnt $a, Nil, 'Nil should not survive being put in a container';

=head2 By approximate numeric comparison

=item X<is-approx($value, $expected, $description?)|is-approx>

Marks a test as passed if the C<$value> and C<$expected> numerical values
are approximately equal to each other. The subroutine can be called in numerous
ways that let you test using relative tolerance (C<$rel-tol>) or
absolute tolerance (C<$abs-tol>) of different values.

If no tolerance is set, the function will base the tolerance on the I<absolute>
value of C<$expected>: if it's smaller than C<1e-6>, use absolute tolerance of C<1e-5>;
if it's larger, use relative tolerance of C<1e-6>.

    my Numeric ($value, $expected, $abs-tol, $rel-tol) = ...

    is-approx $value, $expected;
    is-approx $value, $expected, 'test description';

    is-approx $value, $expected, $abs-tol;
    is-approx $value, $expected, $abs-tol, 'test description';

    is-approx $value, $expected, :$rel-tol;
    is-approx $value, $expected, :$rel-tol, 'test description';

    is-approx $value, $expected, :$abs-tol;
    is-approx $value, $expected, :$abs-tol, 'test description';

    is-approx $value, $expected, :$abs-tol, :$rel-tol;
    is-approx $value, $expected, :$abs-tol, :$rel-tol, 'test description';

=head3 Absolute Tolerance

When an absolute tolerance is set, it's used as the actual maximum value by
which the C<$value> and C<$expected> can differ. For example:

    is-approx 3, 4, 2; # success
    is-approx 3, 6, 2; # fail

    is-approx 300, 302, 2; # success
    is-approx 300, 400, 2; # fail
    is-approx 300, 600, 2; # fail

Regardless of values given, the difference between them cannot be more
than C<2>.

=head3 Relative Tolerance

When a relative tolerance is set, the test checks the relative difference between
values. Given the same tolerance, the larger the numbers given, the larger the
value they can differ by can be.

For example:

    is-approx 10, 10.5, :rel-tol<0.1>; # success
    is-approx 10, 11.5, :rel-tol<0.1>; # fail

    is-approx 100, 105, :rel-tol<0.1>; # success
    is-approx 100, 115, :rel-tol<0.1>; # fail

Both versions use C<0.1> for relative tolerance, yet the first can differ
by about C<1> while the second can differ by about C<10>. The function used
to calculate the difference is:

=begin code :lang<text>
              |value - expected|
⁣rel-diff = ────────────────────────
           max(|value|, |expected|)
=end code

and the test will fail if C<rel-diff> is higher than C<$rel-tol>.

=head3 Both Absolute and Relative Tolerance Specified

=for code :skip-test
is-approx $value, $expected, :rel-tol<.5>, :abs-tol<10>;

When both absolute and relative tolerances are specified, each will be
tested independently, and the C<is-approx> test will succeed only if both pass.

=head2 By structural comparison

=item X<is-deeply($value, $expected, $description?)|is-deeply>

Marks a test as passed if C<$value> and C<$expected> are equivalent, using the
same semantics as the L<eqv operator|/routine/eqv>. This is the best way to
check for equality of (deep) data structures. The function accepts an optional
C<$description> of the test.

=begin code
use v6.c;
use Test;
plan 1;

sub string-info(Str() $_) {
    Map.new: (
      length  =>  .chars,
      char-counts => Bag.new-from-pairs: (
          letters => +.comb(/<:letter>/),
          digits  => +.comb(/<:digit>/),
          other   => +.comb(/<.-:letter-:digit>/),
    ))
}

is-deeply string-info('42 Butterflies ♥ Perl'), Map.new((
    :21length,
    char-counts => Bag.new-from-pairs: ( :15letters, :2digits, :4other, )
)), 'string-info gives right info';
=end code

B<Note:> for L<historical
reasons|https://github.com/rakudo/rakudo/commit/096bc17cd5>, L<Seq:D|/type/Seq> arguments
to C<is-deeply> get converted to L<Lists|/type/List>. If you want to ensure
strict C<Seq> comparisons, use
L«C<cmp-ok $got, 'eqv', $expected, $desc>|/language/testing#index-entry-cmp-ok-cmp-ok%28%24value%2C_%24comparison%2C_%24expected%2C_%24description%3F%29» instead.

=head2 By arbitrary comparison

=item X<cmp-ok(Mu $value is raw, $comparison, Mu $expected is raw, $description?)|cmp-ok>

Compares C<$value> and C<$expected> with the given C<$comparison> comparator and
passes the test if the comparison yields a C<True> value. The C<$description>
of the test is optional.

The C<$comparison> comparator can be either a L<Callable> or
a L<Str> containing an infix operator, such as C<'=='>, a C<'~~'>, or a
user-defined infix.

    cmp-ok 'my spelling is apperling', '~~', /perl/, "bad speller";

Meta operators cannot be given as a string; pass them as a L<Callable> instead:

    cmp-ok <a b c>, &[!eqv], <b d e>, 'not equal';

A L<Callable> C<$comparison> lets you use custom comparisons:

    sub my-comp { $^a / $^b  < rand };
    cmp-ok 1, &my-comp, 2, 'the dice giveth and the dice taketh away'

    cmp-ok 2, -> $a, $b { $a.is-prime and $b.is-prime and $a < $b }, 7,
        'we got primes, one larger than the other!';

=head2 By object type

=item X<isa-ok($value, $expected-type, $description?)|isa-ok>

Marks a test as passed if the given object C<$value> is, or inherits from, the
given C<$expected-type>.  For convenience, types may also be specified as a
string.  The function accepts an optional C<$description> of the test.

    class Womble {}
    class GreatUncleBulgaria is Womble {}
    my $womble = GreatUncleBulgaria.new;

    isa-ok $womble, Womble, "Great Uncle Bulgaria is a womble";
    isa-ok $womble, 'Womble';     # equivalent

=head2 By method name

=item X<can-ok($variable, $method-name, $description?)|can-ok>

Marks a test as passed if the given C<$variable> can run the given
C<$method-name>.  The function accepts an optional C<$description>.  For
instance:

    class Womble {};
    my $womble = Womble.new;

    # with automatically generated test description
    can-ok $womble, 'collect-rubbish';
    #  => An object of type 'Womble' can do the method 'collect-rubbish'

    # with human-generated test description
    can-ok $womble, 'collect-rubbish', "Wombles can collect rubbish";
    #  => Wombles can collect rubbish

=head2 By role

=item X<does-ok($variable, $role, $description?)|does-ok>

Marks a test as passed if the given C<$variable> can do the given C<$role>.
The function accepts an optional C<$description> of the test.

    # create a Womble who can invent
    role Invent {
        method brainstorm { say "Aha!" }
    }
    class Womble {}
    class Tobermory is Womble does Invent {}

    # ... and later in the tests
    use Test;

    my $tobermory = Tobermory.new;

    # with automatically generated test description
    does-ok $tobermory, Invent;
    #  => The object does role Type

    does-ok $tobermory, Invent, "Tobermory can invent";
    #  => Tobermory can invent

=head2 By regex

=item X<like($value, $expected-regex, $description?)|like>

    like 'foo', /fo/, 'foo looks like fo';

Marks a test as passed if the C<$value>, when coerced to a string, matches the
C<$expected-regex>.  The function accepts an optional C<$description> of the
test.

=item X<unlike($value, $expected-regex, $description?)|unlike>

    unlike 'foo', /bar/, 'foo does not look like bar';

Marks a test as passed if the C<$value>, when coerced to a string, does B<not>
match the C<$expected-regex>.  The function accepts an optional C<$description>
of the test.

=head1 Testing modules

=item X<use-ok($module)|use-ok>

Marks a test as passed if the given C<$module> loads correctly.

    use-ok 'Full::Qualified::ModuleName';

=head1 Testing exceptions

=item X<dies-ok($code, $description?)|dies-ok>

Marks a test as passed if the given C<$code> throws an exception.

The function accepts an optional C<$description> of the test.

=begin code
sub saruman(Bool :$ents-destroy-isengard) {
    die "Killed by Wormtongue" if $ents-destroy-isengard;
}

dies-ok { saruman(ents-destroy-isengard => True) }, "Saruman dies";
=end code

=item X<lives-ok($code, $description?)|lives-ok>

Marks a test as passed if the given C<$code> B<does not> throw an
exception.

The function accepts an optional C<$description> of the test.

=begin code
sub frodo(Bool :$destroys-ring) {
    die "Oops, that wasn't supposed to happen" unless $destroys-ring;
}

lives-ok { frodo(destroys-ring => True) }, "Frodo survives";
=end code

=item X<eval-dies-ok($string, $description?)|eval-dies-ok>

Marks a test as passed if the given C<$string> throws an exception when
C<eval>ed as code.

The function accepts an optional C<$description> of the test.

=begin code
eval-dies-ok q[my $joffrey = "nasty";
               die "bye bye Ned" if $joffrey ~~ /nasty/],
    "Ned Stark dies";
=end code

=item X<eval-lives-ok($string, $description?)|eval-lives-ok>

Marks a test as passed if the given C<$string> B<does not> throw an
exception when C<eval>ed as code.

The function accepts an optional C<$description> of the test.

=begin code
eval-lives-ok q[my $daenerys-burns = False;
                die "Oops, Khaleesi now ashes" if $daenerys-burns],
    "Dany is blood of the dragon";
=end code

X<|throws-like>

=item throws-like($code, $expected-exception, $description?, *%matcher)

Marks a test as passed if the given C<$code> throws the specific exception
C<$expected-exception>. The code C<$code> may be specified as something
C<Callable> or as a string to be C<EVAL>ed. The exception may be specified
as a type object or as a string containing its type name.

If an exception was thrown, it will also try to match the matcher hash,
where the key is the name of the method to be called on the exception, and
the value is the value it should have to pass. For example:

=begin code
sub frodo(Bool :$destroys-ring) { fail "Oops. Frodo dies" unless $destroys-ring };
throws-like { frodo }, Exception, message => /dies/;
=end code

The function accepts an optional C<$description> of the test.

The routine makes L<Failures|/type/Failure> fatal. If you wish to avoid that,
use L«C<no fatal> pragma|/language/pragmas#index-entry-fatal-fatal» and ensure the
tested code does not sink the possible L<Failures|/type/Failure>:

    sub fails-not-throws { +"a" }
    # test passes, even though it's just a Failure and would not always throw:
    throws-like { fails-not-throws }, Exception;

    # test detects nothing got thrown, because our Failure wasn't sunk or made fatal:
    throws-like { no fatal; my $ = fails-not-throws; Nil }, Exception;

Please note that you can only use the string form (for C<EVAL>) if you are not referencing
any symbols in the surrounding scope. If you are, you should encapsulate
your string with a block and an EVAL instead. For instance:

    throws-like { EVAL q[ fac("foo") ] }, X::TypeCheck::Argument;

=head1 Grouping tests

The result of a group of subtests is only C<ok> if all subtests are C<ok>.

=item X<subtest(&subtests, $description?)|subtest>

The C<subtest> function executes the given block, consisting of usually more
than one test, possibly including a C<plan> or C<done-testing>, and counts as
I<one> test in C<plan>, C<todo>, or C<skip> counts. It will pass the
test only if B<all> tests in the block pass. The function accepts an
optional C<$description> of the test.

=begin code
class Womble {}

class GreatUncleBulgaria is Womble {
    has $.location = "Wimbledon Common";
    has $.spectacles = True;
}

subtest {
    my $womble = GreatUncleBulgaria.new;

    isa-ok $womble,            Womble,             "Correct type";
    is     $womble.location,   "Wimbledon Common", "Correct location";
    ok     $womble.spectacles,                     "Correct eyewear";

}, "Check Great Uncle Bulgaria";
=end code

You can also place the description as the first positional argument, or use a C<Pair> with description as the key and subtest's code
as the value. This can be useful for subtests with large bodies.

=begin code
subtest 'A bunch of tests', {
    plan 42;
    ...
    ...
}

subtest 'Another bunch of tests' => {
    plan 72;
    ...
    ...
}
=end code

=head1 Skipping tests

Sometimes tests just aren't ready to be run, for instance a feature might
not yet be implemented, in which case tests can be marked as C<todo>. Or it
could be the case that a given feature only works on a particular platform -
in which case one would C<skip> the test on other platforms.

=item X<todo($reason, $count = 1)|todo>

Mark C<$count> tests as TODO, giving a C<$reason> as to why.  By default
only one test will be marked TODO.

    sub my-custom-pi { 3 };

    todo 'not yet precise enough';         # Mark the test as TODO.
    is my-custom-pi(), pi, 'my-custom-pi'; # Run the test, but don't report
                                           # failure in test harness.

The result from the test code above will be something like:

=begin code :lang<TAP>
not ok 1 - my-custom-pi# TODO not yet precise enough

# Failed test 'my-custom-pi'
# at test-todo.t line 7
# expected: '3.14159265358979'
#      got: '3'
=end code

Note that if you C<todo> a C<subtest>, all of the failing tests inside of it will be
automatically marked TODO as well and will I<not> count towards your original TODO count.

=item X<skip($reason, $count = 1)|skip>

Skip C<$count> tests, giving a C<$reason> as to why.  By default only one
test will be skipped.  Use such functionality when a test (or tests) would
die if run.

=begin code
sub num-forward-slashes($arg) { ... } ;

if $*KERNEL ~~ 'linux' {
    is num-forward-slashes("/a/b"),             2;
    is num-forward-slashes("/a//b".IO.cleanup), 2;
}
else {
    skip "Can't use forward slashes on Windows", 2;
}
=end code

Note that if you mark a test as skipped, you must also prevent that
test from running.

=item X<skip-rest($reason?)|skip-rest>

Skip the remaining tests.  If the remainder of the tests in the test file
would all fail due to some condition, use this function to skip them,
providing an optional C<$reason> as to why.

=begin code
my $location; sub womble { ... }; ...;
unless $location ~~ "Wimbledon Common" {
    skip-rest "We can't womble, the remaining tests will fail";
    exit;
}

# tests requiring functional wombling
ok womble();
# ...
=end code

Note that C<skip-rest> requires a C<plan> to be set, otherwise the
C<skip-rest> call will throw an error. Note that C<skip-rest> does
not exit the test run. Do it manually, or use conditionals to
avoid running any further tests.

See also L«C<plan :skip-all('...')>|/language/testing#index-entry-plan-plan($count)»
to avoid running any tests at all and
L«C<bail-out>|/language/testing#index-entry-bail-out-bail-out($reason?)» to abort
the test run and mark it as failed.

=item X<bail-out($reason?)|bail-out>

If you already know the tests will fail, you can bail out of the test run
using C<bail-out()>:

=begin code
my $has-db-connection;
...
$has-db-connection  or bail-out 'Must have database connection for testing';
=end code

The function aborts the current test run, signaling failure to the harness.
Takes an optional reason for bailing out. The subroutine will call
C<exit()>, so if you need to do a clean-up, do it before calling C<bail-out()>.

If you want to abort the test run, but without marking it as failed, see
L«C<skip-rest>|/language/testing#index-entry-skip-rest-skip-rest($reason?)»
or L«C<plan :skip-all('...')>|/language/testing#index-entry-plan-plan($count)»

=head1 Manual control

If the convenience functionality documented above does not suit your needs,
you can use the following functions to manually direct the test harness
output.

=item X<pass($description?), flunk($description?)|pass;flunk>

The C<pass> function marks a test as passed. C<flunk> marks a test as
B<not> passed. Both functions accept an optional test C<$description>.

    pass "Actually, this test has passed";

    flunk "But this one hasn't passed";

Since these subroutines do not provide indication of what value was received
and what was expected, they should be used sparingly, such as when evaluating
a complex test condition.

=item X<diag($message)|diag>

Display diagnostic information in a TAP-compatible manner on the standard
error stream. This is usually used when a particular test has failed to
provide information that the test itself did not provide.  Or it can be used
to provide visual markers on how the testing of a test-file is progressing
(which can be important when doing stress testing).

    diag "Yay!  The tests got to here!";

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
